[iOS 10] 音声認識から得た文章の形態素解析と品詞分解をしてみた
おばんです、iPhoneは5を使っていますが4世代前ということに気づいてさすがに買い替えを検討し始めている田中です。iPhone 6sあたりがほしい。
今回の記事は【iOS 10】SFSpeechRecognizerで音声認識を試してみた | Developers.IOの続きとなります。 出てくるソースコードも、この記事が前提となります。
タイトルはiOS 10と一応銘打ってはいますが、今回使うNSLinguisticTaggerは特にiOS 10からの新機能というわけではなくSFSpeechRecognizerとの合わせ技でiOS 10とつけていますのであしからず。
NSLinguisticTaggerって?
自然言語のテキストを形態素解析してくれたり品詞分解してくれるクラスです。
NSLinguisticTaggerで形態素解析してみる
前回のソースコードに以下の拡張を書きます。
extension ViewController { func analyzeText(text: String) { // "en" = 英語 // "ja" = 日本語 let tagger = NSLinguisticTagger(tagSchemes: NSLinguisticTagger.availableTagSchemes(forLanguage: "ja"), options: 0) tagger.string = text // NSLinguisticTagSchemeTokenType // Word, Punctuation, Whitespace, Otherで判別が可能。今回はoptionsで.omitWhitespaceを設定して空白を無視するようにしています。 tagger.enumerateTags(in: NSRange(location: 0, length: text.characters.count), scheme: NSLinguisticTagSchemeTokenType, options: [.omitWhitespace]) { tag, tokenRange, sentenceRange, stop in let subString = (text as NSString).substring(with: tokenRange) print("\(subString) : \(tag)") } } }
この時、解析する言語に合わせてspeechRecognizerのLocaleも変更しておきましょう。 (変更しないと、英語を喋っているのに日本語が入力として受け取られたりします)
// "ja-JP"を指定すると日本語になります。 // "en-US"でアメリカ英語 private let speechRecognizer = SFSpeechRecognizer(locale: Locale(identifier: "ja-JP"))!
追加した拡張を発話の受け取り部分で使用します。
recognitionTask = speechRecognizer.recognitionTask(with: recognitionRequest) { [weak self] result, error in guard let `self` = self else { return } var isFinal = false if let result = result { self.label.text = result.bestTranscription.formattedString isFinal = result.isFinal // analyzeTextにbestTranscriptionを渡す self.analyzeText(text: result.bestTranscription.formattedString) } // エラー処理 ......... ...... ... }
実行結果
日本語
某アニメの僕の嫁のセリフから
「私ね、大学は医学部って決まってるの。だから、私の音楽はもう終わってるってわけ。」
私 : Word ね : Word 、 : Punctuation 大学 : Word は : Word 医学 : Word 部 : Word って : Word 決まっ : Word て : Word いる : Word の : Word 。 : Punctuation だ : Word から : Word 、 : Punctuation 私 : Word の : Word 音楽 : Word は : Word もう : Word 終 : Word わっ : Word てる : Word って : Word わけ : Word 。 : Punctuation
英語
ジョブズのスピーチから、
"The first story is about connecting the dots."
The : Word first : Word story : Word is : Word about : Word connecting : Word the : Word dots : Word
NSLinguisticTaggerで品詞分解をしてみる
availableで調べると品詞分解は日本語が非対応でできないため英語でやります。
extension ViewController { func analyzeText(text: String) { // "en" = 英語 // "ja" = 日本語 let tagger = NSLinguisticTagger(tagSchemes: NSLinguisticTagger.availableTagSchemes(forLanguage: "en"), options: 0) tagger.string = text // NSLinguisticTagSchemeLexicalClass // 品詞、イディオムなどで判別が可能。日本語は非対応。今回はoptionsで.omitWhitespaceを設定して空白を無視するようにしています。 tagger.enumerateTags(in: NSRange(location: 0, length: text.characters.count), scheme: NSLinguisticTagSchemeLexicalClass, options: [.omitWhitespace]) { tag, tokenRange, sentenceRange, stop in let subString = (text as NSString).substring(with: tokenRange) print("\(subString) : \(tag)") } } }
実行結果
The : Determiner first : Adjective story : Noun is : Verb about : Preposition connecting : Verb the : Determiner dots : Noun
ハラショー、完璧に分解してくれています。
まとめ
やはりオフィスで人が聞いてる中で急に英語喋るのとかなかなかハードル高いですねw 大学時代はほんのちょっとだけこのあたりのことをやっていたので懐かしく感じました。
音声認識に関しては日本語、英語とも良いのであとはそのデータをどう扱うかというところで語の分解・解析等のサンプルとして書いてみました。 またここから二次加工としてどうするかでアプリのネタや要素になりそうかとも思います。(例えば端末内辞書と照らし合わせてゴニョゴニョなアプリとか)
参考
- 【iOS 10】SFSpeechRecognizerで音声認識を試してみた | Developers.IO
- NSLinguisticTagSchemeLexicalClass - Foundation | Apple Developer Documentation
- NSLinguisticTagSchemeLexicalClass - Foundation | Apple Developer Documentation
- NSLinguisticTagSchemeTokenType - Foundation | Apple Developer Documentation
- 自然言語のテキストを属性で区分する - Qiita
- Swift での自然言語処理